package com.ctgu.tengyun.util;

import com.ctgu.tengyun.exception.RequestValidateException;
import com.ctgu.tengyun.exception.TengyunRuntimeException;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

public class ServletFileUploadUtil {
	
	private static final Logger logger = LoggerFactory.getLogger(ServletFileUploadUtil.class);
	
//	public static HashSet<String> INNER_SUPPORT_FORMAT = new HashSet<String>(Arrays.asList(new String[]{"jpg", "png", "gif"}));
//    public static HashSet<String> USER_SUPPORT_GIF_FORMAT = new HashSet<String>(Arrays.asList(new String[]{MediaFileFormat.gif.name(),
//        MediaFileFormat.png.name(), MediaFileFormat.jpeg.name()}));
//	public static HashSet<String> USER_SUPPORT_FORMAT = new HashSet<String>(Arrays.asList(new String[]{MediaFileFormat.jpg.name(),
//			MediaFileFormat.png.name(), MediaFileFormat.jpeg.name()}));
//	public static HashSet<String> USER_SUPPORT_FILE_FORMAT = new HashSet<String>(
//			Arrays.asList(new String[]{MediaFileFormat.doc.name(), MediaFileFormat.docx.name(), MediaFileFormat.xls.name(), MediaFileFormat.xlsx.name(),
//					MediaFileFormat.ppt.name(), MediaFileFormat.pptx.name(), MediaFileFormat.pdf.name()}));
	
	public static ServletFileUpload initServletFileUpload(File tmpStore, Integer sizeMax){
		
		//1、创建一个DiskFileItemFactory工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();        
        factory.setRepository(tmpStore);          
        //2、创建一个文件上传解析器
        ServletFileUpload upload = new ServletFileUpload(factory);      
        upload.setSizeMax(sizeMax);
        //解决上传文件名的中文乱码
        upload.setHeaderEncoding("UTF-8");
		
        return upload;
	}
	
	public static String parseFormat(String fileName){
		if( fileName.lastIndexOf(".") > 0 ) {
			return fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
		} else {
			return StringUtils.EMPTY;
		}
	}
	
	public static String parseFormat(FileItem uploadFileItem, HashSet<String> supportFormat ){
		String filename = uploadFileItem.getName();
        if(StringUtils.isEmpty(filename)){
        	throw new RequestValidateException("filename is null or empty.", "filename is null or empty.");
        }
    	File f = new File(filename);
    	filename = f.getName();
    	String format = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
    	validateFormat(format, supportFormat);
    	
    	return format;
	}

	private static String validateFormat(String format, HashSet<String> supportFormat){
		if( !StringUtils.isEmpty(format) ) {			
			String f = format.toLowerCase();
			if( supportFormat.contains(f) ) {
				return f;
			}		
		}
		throw new RequestValidateException("unsupported format. format:" + format, "unsupported format.");
	}
	
	public static FileItem parseFileItem(HttpServletRequest request, ServletFileUpload upload){
		
		FileItem uploadFileItem = null;
		try {
			//4、使用ServletFileUpload解析器解析上传数据，解析结果返回的是一个List<FileItem>集合，每一个FileItem对应一个Form表单的输入项
			List<FileItem> list = upload.parseRequest(request);
			for (Iterator<FileItem> it = list.iterator(); it.hasNext(); ) {
				FileItem item = it.next();
				if( !item.isFormField() || uploadFileItem == null ) {					
					uploadFileItem = item;
				} else {
					item.delete(); //只读第一个uploadFileItem。其他delete
				}
			}
		} catch (FileUploadException e) {
			throw new RequestValidateException(e.getMessage(), e.getMessage(), e);
		}
		
		return uploadFileItem;
	}
	
	public static void writeToFile(FileItem uploadFileItem, String outputPath){
		InputStream in = null;
    	try {
    		in = uploadFileItem.getInputStream();
    		//获取item中的上传文件的输入流
			writeToFile(in, outputPath);
		} catch (IOException e) {
			throw new TengyunRuntimeException("save file error.", e);
		} finally {
			if( in != null ) {
				try {
					in.close();
				} catch (IOException ignore) {
					logger.warn("close input stream error.", ignore);
				}
			}
		}
	}
	
	public static void writeToFile(InputStream in, String outputPath){
    	FileOutputStream out = null;
    	try {
	        //创建一个文件输出流
	        out = new FileOutputStream(outputPath);
	        //创建一个缓冲区
	        byte buffer[] = new byte[1024];
	        //判断输入流中的数据是否已经读完的标识
	        int len = 0;
	        //循环将输入流读入到缓冲区当中，(len=in.read(buffer))>0就表示in里面还有数据
	        while((len=in.read(buffer))>0){
	            //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
	            out.write(buffer, 0, len);
	        }	        
	        out.flush();	       
		} catch (IOException e) {
			throw new TengyunRuntimeException("save file error.", e);
		} finally {
			if( in != null ) {
				try {
					in.close();
				} catch (IOException ignore) {
					logger.warn("close input stream error.", ignore);
				}
			}
			
			if( out != null ) {
				try {
					out.close();
				} catch (IOException ignore) {
					logger.warn("close output stream error.", ignore);
				}				
			}		
		}
	}
	
}
